let currentUrl

// 获取当前 tab 的 url ，需要 开启 tabs 权限
const getCurrentTabUrl = async () => {
  return new Promise(resolve => {
    chrome.tabs.query({ active: true, currentWindow: true }, (tabs) => {
      const url = tabs[0].url
      resolve(url)
    })
  })
}

// 小驼峰
const toLowerCamelCase = (str) => {
  return str.charAt(0).toLowerCase() + str.slice(1)?.replace('-', '')
}
// 大驼峰
const toUpperCamelCase = (str) => {
  return str.charAt(0).toUpperCase() + str.slice(1)?.replace('-', '')
}

// 截取拼接方法名, 驼峰
const getApiName = (path) => {
  const apiNameArr = path.split('/').filter(v => !(v.includes('{') || v.includes('}')))
  const len = apiNameArr.length
  const title = (apiNameArr[len - 2] || '').trim()
  const subTitle = (apiNameArr[len - 1] || '').trim()
  const titleStr = title?.split('-')?.map(v => toUpperCamelCase(v))?.join('')
  const subTitleStr = subTitle?.split('-')?.map(v => toUpperCamelCase(v))?.join('')
  const apiName = `${toLowerCamelCase(titleStr)}${subTitleStr}`
  return apiName
}

// json-schema-to-typescript 配置
const options = {
  // banner
  bannerComment: '',
  // 是否需要其他属性 例如 [k: string]: unknown
  additionalProperties: false,
};

// 清除default
const clearDefaultValue = (obj) => {
  const clearKey = 'default'
  if (Reflect.has(obj, clearKey)) {
    Reflect.deleteProperty(obj, clearKey)
  }
  if (obj.properties) {
    const keys = Object.keys(obj.properties)
    keys.forEach(key => {
      const item = obj.properties[key]
      item && clearDefaultValue(item)
    })
  }
}

// 将 integer 类型转 string
const integerToString = (obj) => {
  const res = obj.properties || obj.items?.properties
  if (res) {
    const keys = Object.keys(res)
    keys.forEach(key => {
      const item = res[key]
      if (item && !['pageNum', 'pageSize', 'createdTime'].includes(key)) {
        const isInteger = item.type === 'integer'
        const isIntegerArr = item.type === 'array' && item.items.type === 'integer'
        if (isInteger) item.type = 'string'
        if (isIntegerArr) item.items.type = 'string'
        integerToString(item)
      }
    })
  }
}

// 将路径参数 数组 转成对象
const tranformUrlQuery = (arg) => {
  if (Array.isArray(arg)) {
    const obj = {
      description: '',
      properties: {}
    }
    arg.forEach(item => {
      obj.properties[item.name] = {
        type: 'string',
        description: item.desc
      }
    })
    return obj
  }
  return arg
}

// 处理类型声明嵌套
const handleNestedInterface = (data, topTypeName) => {
  const originObj = data
  originObj.definitions = {}
  const mapFn = (obj, parentTypeName) => {
    if (obj.type === 'array' && ['object', 'array'].includes(obj.items?.type)) {
      const typeKey = `${parentTypeName}Item`
      originObj.definitions[typeKey] = { ...obj.items }
      obj.items.$ref = `#/definitions/${typeKey}`
      mapFn(obj.items, typeKey)
    }
    if (obj && obj.properties) {
      const keys = Object.keys(obj.properties)
      keys?.forEach(key => {
        const item = obj.properties[key]
        if (item.type === 'object') {
          const typeName = `${parentTypeName}${toUpperCamelCase(key)}`
          originObj.definitions[typeName] = { ...item, desc: item.description }
          item.$ref = `#/definitions/${typeName}`
          mapFn(item, typeName)
        }
        if (item.type === 'array' && ['object', 'array'].includes(item.items?.type)) {
          const typeName = `${parentTypeName}${toUpperCamelCase(key)}Item`
          originObj.definitions[typeName] = { ...item.items }
          item.items.$ref = `#/definitions/${typeName}`
          mapFn(item.items, typeName)
        }
      })
    }
  }
  console.log(originObj, topTypeName)
  mapFn(originObj, topTypeName)
}

// 入参 类型
const parseReq = async (data, reqTypeName) => {
  const { title, req_body_is_json_schema, req_params, req_query, req_body_other } = data
  const reqBody = req_body_is_json_schema ? JSON.parse(req_body_other) : {}
  let reqQuery = [...req_params, ...req_query]
  // 拼接描述
  if (reqBody.description) {
    reqBody.description = `${title} - ${reqBody.description}\nyapi地址：${currentUrl}`
  } else {
    reqBody.description = title + `\nyapi地址：${currentUrl}`
  }

  // 处理路径参数
  reqQuery = tranformUrlQuery(reqQuery)

  const req = {
    ...reqQuery,
    ...reqBody,
  }

  // 清除default
  clearDefaultValue(req)

  // integer 转 string
  integerToString(req)

  // 处理嵌套声明
  handleNestedInterface(req, reqTypeName)

  return req
}

// 回参 类型
const parseRes = (data, resTypeName) => {
  const { res_body } = data
  let resBody = JSON.parse(res_body)

  // 修正数据，直接取 data 字段
  if (resBody?.properties?.data) {
    resBody = resBody?.properties?.data
  }

  // 清除详情描述
  resBody.description = ''

  // 清除default
  clearDefaultValue(resBody)

  // 处理 integer 为 string
  integerToString(resBody)

  // 处理嵌套声明
  handleNestedInterface(resBody, resTypeName)

  return resBody
}

// 生成 api TODO: 处理路径参数 - 处理入参出参为 null 时类型
const createApi = async (data, reqTypeName, resTypeName) => {
  const { method, path } = data
  const apiName = getApiName(data.path)
  const _method = method.toLowerCase()
  const paramsKey = _method === 'get' ? 'params' : 'data'
  const api = `
/**
 * ${data.title}
 * @see yapi地址： ${currentUrl}
 */
export const ${apiName}Api = (${paramsKey}: Types.${reqTypeName}) => {
  const url = '${path}'
  return http.${_method}<Types.${resTypeName}>({
    server: DOMAIN_SYSTEM_ENUM.MAIN,
    url,
    ${paramsKey},
    loading: true
  })
}
  `
  return api
}

// 生成类型
const compileType = async (data) => {
  console.log('[storage]', data)
  const apiName = getApiName(data.path)

  const reqTypeName = `I${toUpperCamelCase(apiName)}Req`
  const resTypeName = `I${toUpperCamelCase(apiName)}Res`

  const reqBody = await parseReq(data, reqTypeName)
  const resBody = parseRes(data, resTypeName)

  console.log('--reqBody--', reqBody, resBody)

  const reqType = await window.jstt.compile(reqBody, reqTypeName, options)
  const resType = await window.jstt.compile(resBody, resTypeName, options)

  const api = await createApi(data, reqTypeName, resTypeName)

  const dataTypeArr = [reqType, resType, api]
  const dataType = dataTypeArr.join('\n')

  return dataType;
}

const isYapiInterfaceUrl = (url) => {
  return url.includes('yapi') && url.includes('/interface/api')
}

// 固定本地储存 key
const RES_KEY = 'res_key'
// init
const init = async () => {
  currentUrl = await getCurrentTabUrl()
  if (!isYapiInterfaceUrl(currentUrl)) {
    return
  }
  chrome.storage.local.get(RES_KEY, async (item) => {
    const res = item[RES_KEY]
    const page = await compileType(res.data)
    // 挂载到 popup.html 容器
    const editor = monaco.editor.create(document.querySelector('#chrome_plugin_demo_popup_id'), {
      value: page,
      language: 'typescript'
    })
    console.log('[editor]', editor)
    // 忽略未定义的变量
    monaco.languages.typescript.typescriptDefaults.setCompilerOptions({
      noImplicitAny: false,
      noUnusedLocals: false,
      noUnusedParameters: false
    })
  })
}

window.addEventListener('load', init)
